package org.ruoyi.interview.config;

import lombok.Data;
import org.ruoyi.interview.controller.InterviewAIWebSocketController;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.WebSocket;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.util.*;
import java.util.concurrent.*;

@Configuration
@Data
public class Ultra {

    @Value("${xunfei.spark.api-key}")
    private String apiKey;

    @Value("${xunfei.spark.api-secret}")
    private String apiSecret;

    @Value("${xunfei.spark.app-id}")
    private String appId;

    public String chat(String question) throws Exception {
        return chat(question, new ArrayList<>());
    }

    public String chat(String question, List<RoleContent> historyList) throws Exception {
        // 获取鉴权URL
        String authUrl = getAuthUrl();

        // 创建WebSocket客户端
        XunfeiWebSocketClient client = new XunfeiWebSocketClient(this.appId);

        // 启动客户端连接
        client.connectBlocking(authUrl);

        // 构建请求参数
        String requestJson = buildRequestJson(question, historyList);

        // 发送请求
        client.sendText(requestJson);

        // 等待并获取结果
        String result = client.getResult();

        // 关闭连接
        client.closeBlocking();

        // 添加模型回复到历史记录
        RoleContent assistantRoleContent = new RoleContent();
        assistantRoleContent.role = "assistant";
        assistantRoleContent.content = result;
        if (historyList != null) {
            historyList.add(assistantRoleContent);
        }

        return result;
    }

    /**
     * 构建请求JSON
     */
    private String buildRequestJson(String question, List<RoleContent> historyList) {
        // 使用HashMap模拟JSON对象
        Map<String, Object> jsonObject = new HashMap<>();

        // header部分
        Map<String, Object> header = new HashMap<>();
        header.put("app_id", this.appId);
        header.put("uid", "123456");
        jsonObject.put("header", header);

        // parameter部分
        Map<String, Object> parameter = new HashMap<>();
        Map<String, Object> chat = new HashMap<>();
        chat.put("domain", "lite");
        chat.put("temperature", 0.5);
        chat.put("max_tokens", 1024);
        parameter.put("chat", chat);
        jsonObject.put("parameter", parameter);

        // payload部分
        Map<String, Object> payload = new HashMap<>();
        List<Map<String, String>> messagesArray = new ArrayList<>();

        // 历史信息获取，如果有则携带
        if (historyList != null && !historyList.isEmpty()) {
            for (RoleContent tempRoleContent : historyList) {
                Map<String, String> message = new HashMap<>();
                message.put("role", tempRoleContent.role);
                message.put("content", tempRoleContent.content);
                messagesArray.add(message);
            }
        }

        // 拼接最新问题
        Map<String, String> message = new HashMap<>();
        message.put("role", "user");
        message.put("content", question);
        messagesArray.add(message);

        Map<String, Object> text = new HashMap<>();
        text.put("text", messagesArray);
        payload.put("message", text);
        jsonObject.put("payload", payload);

        // 简单的JSON序列化
        return toJsonString(jsonObject);
    }

    /**
     * 简单的JSON序列化方法
     */
    private String toJsonString(Object obj) {
        if (obj instanceof Map) {
            Map<?, ?> map = (Map<?, ?>) obj;
            StringBuilder sb = new StringBuilder("{");
            boolean first = true;
            for (Map.Entry<?, ?> entry : map.entrySet()) {
                if (!first) {
                    sb.append(",");
                }
                sb.append("\"").append(entry.getKey()).append("\":");
                sb.append(toJsonString(entry.getValue()));
                first = false;
            }
            sb.append("}");
            return sb.toString();
        } else if (obj instanceof List) {
            List<?> list = (List<?>) obj;
            StringBuilder sb = new StringBuilder("[");
            boolean first = true;
            for (Object item : list) {
                if (!first) {
                    sb.append(",");
                }
                sb.append(toJsonString(item));
                first = false;
            }
            sb.append("]");
            return sb.toString();
        } else if (obj instanceof String) {
            return "\"" + obj.toString() + "\"";
        } else {
            return obj.toString();
        }
    }

    /**
     * 获取鉴权URL
     */
    public String getAuthUrl() throws Exception {
        String hostUrl = "wss://spark-api.xf-yun.com/v1.1/chat";

        SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
        format.setTimeZone(TimeZone.getTimeZone("GMT"));
        String date = format.format(new Date());

        String signatureOrigin = "host: spark-api.xf-yun.com\n" +
                               "date: " + date + "\n" +
                               "GET /v1.1/chat HTTP/1.1";

        SecretKeySpec signKey = new SecretKeySpec(this.apiSecret.getBytes(StandardCharsets.UTF_8), "hmacsha256");
        Mac mac = Mac.getInstance("hmacsha256");
        mac.init(signKey);
        byte[] signatureBytes = mac.doFinal(signatureOrigin.getBytes(StandardCharsets.UTF_8));
        String signature = Base64.getEncoder().encodeToString(signatureBytes);

        String authorizationOrigin = "api_key=\"" + this.apiKey + "\", algorithm=\"hmac-sha256\", headers=\"host date request-line\", signature=\"" + signature + "\"";
        String authorization = Base64.getEncoder().encodeToString(authorizationOrigin.getBytes(StandardCharsets.UTF_8));

        return hostUrl + "?authorization=" + URLEncoder.encode(authorization, "UTF-8") + "&date=" + URLEncoder.encode(date, "UTF-8") + "&host=spark-api.xf-yun.com";
    }

    public static class RoleContent {
        String role;
        String content;

        public String getRole() {
            return role;
        }

        public void setRole(String role) {
            this.role = role;
        }

        public String getContent() {
            return content;
        }

        public void setContent(String content) {
            this.content = content;
        }
    }

    /**
     * 讯飞WebSocket客户端实现
     */
    private static class XunfeiWebSocketClient implements WebSocket.Listener {
        private final StringBuilder resultBuilder = new StringBuilder();
        private final CountDownLatch closeLatch = new CountDownLatch(1);
        private final String appId;
        private WebSocket webSocket;

        public XunfeiWebSocketClient(String appId) {
            this.appId = appId;
        }

        /**
         * 建立连接
         */
        public void connectBlocking(String url) throws InterruptedException {
            HttpClient client = HttpClient.newHttpClient();
            CompletableFuture<WebSocket> ws = client.newWebSocketBuilder()
                    .connectTimeout(Duration.ofSeconds(10))
                    .buildAsync(URI.create(url), this);

            webSocket = ws.join(); // 等待连接建立
        }

        /**
         * 发送文本消息
         */
        public void sendText(String text) {
            if (webSocket != null) {
                webSocket.sendText(text, true);
            }
        }

        /**
         * 关闭连接
         */
        public void closeBlocking() throws InterruptedException {
            if (webSocket != null) {
                webSocket.sendClose(WebSocket.NORMAL_CLOSURE, "ok").join();
            }
            // 等待连接关闭
            closeLatch.await(5, TimeUnit.SECONDS);
        }

        @Override
        public void onOpen(WebSocket webSocket) {
            System.out.println("WebSocket连接已建立");
            webSocket.request(1);
        }

        @Override
        public CompletionStage<?> onText(WebSocket webSocket, CharSequence data, boolean last) {
            try {
                String message = data.toString();
                // 简单解析JSON响应
                Map<String, Object> jsonObject = parseJson(message);
                Map<String, Object> header = (Map<String, Object>) jsonObject.get("header");
                Map<String, Object> payload = (Map<String, Object>) jsonObject.get("payload");

                if (payload != null && payload.containsKey("choices")) {
                    Map<String, Object> choices = (Map<String, Object>) payload.get("choices");
                    if (choices.containsKey("text")) {
                        List<Map<String, String>> textArray = (List<Map<String, String>>) choices.get("text");
                        if (textArray != null && !textArray.isEmpty()) {
                            Map<String, String> textObj = textArray.get(0);
                            String content = textObj.get("content");
                            if (content != null) {
                                resultBuilder.append(content);
                            }
                        }
                    }
                }

                // 检查是否结束
                if (header != null && (Integer) header.get("code") == 0) {
                    if (header.containsKey("status") && (Integer) header.get("status") == 2) {
                        closeLatch.countDown();
                    }
                }

            } catch (Exception e) {
                e.printStackTrace();
            }

            webSocket.request(1);
            return WebSocket.Listener.super.onText(webSocket, data, last);
        }

        @Override
        public CompletionStage<?> onBinary(WebSocket webSocket, ByteBuffer data, boolean last) {
            webSocket.request(1);
            return WebSocket.Listener.super.onBinary(webSocket, data, last);
        }

        @Override
        public CompletionStage<?> onClose(WebSocket webSocket, int statusCode, String reason) {
            System.out.println("WebSocket连接已关闭: " + reason);
            closeLatch.countDown();
            return WebSocket.Listener.super.onClose(webSocket, statusCode, reason);
        }

        @Override
        public void onError(WebSocket webSocket, Throwable error) {
            System.err.println("WebSocket发生错误: " + error.getMessage());
            error.printStackTrace();
            closeLatch.countDown();
        }

        /**
         * 获取最终结果
         */
        public String getResult() throws InterruptedException {
            // 等待完成或超时(30秒)
            boolean completed = closeLatch.await(30, TimeUnit.SECONDS);
            if (!completed) {
                throw new RuntimeException("WebSocket等待响应超时");
            }
            return resultBuilder.toString();
        }

        /**
         * 简单的JSON解析方法
         */
        private Map<String, Object> parseJson(String json) {
            // 这里应该使用真正的JSON解析库，但为了简化，我们只处理关键字段
            Map<String, Object> result = new HashMap<>();

            // 简单提取header部分
            int headerStart = json.indexOf("\"header\":");
            if (headerStart != -1) {
                int headerEnd = json.indexOf("}", headerStart);
                if (headerEnd != -1) {
                    String headerStr = json.substring(headerStart, headerEnd + 1);
                    result.put("header", parseSimpleObject(headerStr));
                }
            }

            // 简单提取payload部分
            int payloadStart = json.indexOf("\"payload\":");
            if (payloadStart != -1) {
                int payloadEnd = findMatchingBrace(json, payloadStart);
                if (payloadEnd != -1) {
                    String payloadStr = json.substring(payloadStart, payloadEnd + 1);
                    result.put("payload", parseSimpleObject(payloadStr));
                }
            }

            return result;
        }

        private Map<String, Object> parseSimpleObject(String str) {
            Map<String, Object> result = new HashMap<>();
            // 这里只是一个非常简化的实现，实际应该使用JSON库
            return result;
        }

        private int findMatchingBrace(String str, int start) {
            int braceCount = 0;
            for (int i = start; i < str.length(); i++) {
                char c = str.charAt(i);
                if (c == '{') {
                    braceCount++;
                } else if (c == '}') {
                    braceCount--;
                    if (braceCount == 0) {
                        return i;
                    }
                }
            }
            return -1;
        }
    }

    /**
     * 流式回调接口
     */
    public interface StreamCallback {
        /**
         * 收到消息片段时调用
         * @param message 消息片段
         */
        void onMessage(String message);

        /**
         * 完成时调用
         * @param finalResult 最终结果
         */
        void onComplete(String finalResult);

        /**
         * 发生错误时调用
         * @param e 异常
         */
        void onError(Exception e);
    }

    /**
     * 讯飞WebSocket客户端实现（流式）
     */
    public static class XunfeiWebSocketClientStream implements WebSocket.Listener {
        private final StringBuilder resultBuilder = new StringBuilder();
        private final CountDownLatch closeLatch = new CountDownLatch(1);
        private final String appId;
        private final StreamCallback callback;
        private WebSocket webSocket;
        private boolean isCompleted = false;

        public XunfeiWebSocketClientStream(String appId, StreamCallback callback) {
            this.appId = appId;
            this.callback = callback;
        }

        /**
         * 建立连接
         */
        public void connectBlocking(String url) throws InterruptedException {
            HttpClient client = HttpClient.newHttpClient();
            CompletableFuture<WebSocket> ws = client.newWebSocketBuilder()
                    .connectTimeout(Duration.ofSeconds(10))
                    .buildAsync(URI.create(url), this);

            webSocket = ws.join(); // 等待连接建立
        }

        /**
         * 发送文本消息
         */
        public void sendText(String text) {
            if (webSocket != null) {
                webSocket.sendText(text, true);
            }
        }

        /**
         * 关闭连接
         */
        public void closeBlocking() throws InterruptedException {
            if (webSocket != null) {
                webSocket.sendClose(WebSocket.NORMAL_CLOSURE, "ok").join();
            }
            // 等待连接关闭
            closeLatch.await(5, TimeUnit.SECONDS);
        }

        /**
         * 等待完成
         */
        public void waitForCompletion() throws InterruptedException {
            closeLatch.await(30, TimeUnit.SECONDS);
        }

        /**
         * 获取最终结果
         */
        public String getFinalResult() {
            return resultBuilder.toString();
        }

        @Override
        public void onOpen(WebSocket webSocket) {
            System.out.println("WebSocket连接已建立");
            webSocket.request(1);
        }

        @Override
        public CompletionStage<?> onText(WebSocket webSocket, CharSequence data, boolean last) {
            try {
                String message = data.toString();
                // 简单解析JSON响应
                Map<String, Object> jsonObject = parseJson(message);
                Map<String, Object> header = (Map<String, Object>) jsonObject.get("header");
                Map<String, Object> payload = (Map<String, Object>) jsonObject.get("payload");

                if (payload != null && payload.containsKey("choices")) {
                    Map<String, Object> choices = (Map<String, Object>) payload.get("choices");
                    if (choices.containsKey("text")) {
                        List<Map<String, String>> textArray = (List<Map<String, String>>) choices.get("text");
                        if (textArray != null && !textArray.isEmpty()) {
                            Map<String, String> textObj = textArray.get(0);
                            String content = textObj.get("content");
                            if (content != null) {
                                resultBuilder.append(content);
                                callback.onMessage(content);
                            }
                        }
                    }
                }

                // 检查是否结束
                if (header != null && (Integer) header.get("code") == 0) {
                    if (header.containsKey("status") && (Integer) header.get("status") == 2) {
                        closeLatch.countDown();
                        isCompleted = true;
                    }
                }

            } catch (Exception e) {
                e.printStackTrace();
            }

            webSocket.request(1);
            return WebSocket.Listener.super.onText(webSocket, data, last);
        }

        @Override
        public CompletionStage<?> onBinary(WebSocket webSocket, ByteBuffer data, boolean last) {
            webSocket.request(1);
            return WebSocket.Listener.super.onBinary(webSocket, data, last);
        }

        @Override
        public CompletionStage<?> onClose(WebSocket webSocket, int statusCode, String reason) {
            System.out.println("WebSocket连接已关闭: " + reason);
            closeLatch.countDown();
            return WebSocket.Listener.super.onClose(webSocket, statusCode, reason);
        }

        @Override
        public void onError(WebSocket webSocket, Throwable error) {
            System.err.println("WebSocket发生错误: " + error.getMessage());
            error.printStackTrace();
            closeLatch.countDown();
        }

        /**
         * 简单的JSON解析方法
         */
        private Map<String, Object> parseJson(String json) {
            // 这里应该使用真正的JSON解析库，但为了简化，我们只处理关键字段
            Map<String, Object> result = new HashMap<>();

            // 简单提取header部分
            int headerStart = json.indexOf("\"header\":");
            if (headerStart != -1) {
                int headerEnd = json.indexOf("}", headerStart);
                if (headerEnd != -1) {
                    String headerStr = json.substring(headerStart, headerEnd + 1);
                    result.put("header", parseSimpleObject(headerStr));
                }
            }

            // 简单提取payload部分
            int payloadStart = json.indexOf("\"payload\":");
            if (payloadStart != -1) {
                int payloadEnd = findMatchingBrace(json, payloadStart);
                if (payloadEnd != -1) {
                    String payloadStr = json.substring(payloadStart, payloadEnd + 1);
                    result.put("payload", parseSimpleObject(payloadStr));
                }
            }

            return result;
        }

        private Map<String, Object> parseSimpleObject(String str) {
            Map<String, Object> result = new HashMap<>();
            // 这里只是一个非常简化的实现，实际应该使用JSON库
            return result;
        }

        private int findMatchingBrace(String str, int start) {
            int braceCount = 0;
            for (int i = start; i < str.length(); i++) {
                char c = str.charAt(i);
                if (c == '{') {
                    braceCount++;
                } else if (c == '}') {
                    braceCount--;
                    if (braceCount == 0) {
                        return i;
                    }
                }
            }
            return -1;
        }
    }

    // 使用示例
    public static void main(String[] args) {
        Ultra ultra = new Ultra();
        // 注意：这些值需要从配置文件中获取，这里仅作示例
        // 实际使用时应通过Spring注入
        ultra.apiKey = "your_api_key";
        ultra.apiSecret = "your_api_secret";
        ultra.appId = "your_app_id";

        List<RoleContent> historyList = new ArrayList<>();

        try {
            String question = "请介绍一下人工智能的发展历程";
            String response = ultra.chat(question, historyList);
            System.out.println("星火：" + response);

            // 第二轮对话
            String question2 = "请详细说明其中的机器学习发展";
            String response2 = ultra.chat(question2, historyList);
            System.out.println("星火：" + response2);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
